package com.cgc.venus.server.ci.service;
import com.cgc.venus.server.ci.inter.CIService;
import com.cgc.venus.server.ci.model.dao.CodeSourceDao;
import com.cgc.venus.server.ci.model.dao.PipelineDao;
import com.cgc.venus.server.ci.model.dto.PipelineJobDTO;
import com.cgc.venus.server.ci.model.dto.PipelineStageDTO;
import com.cgc.venus.server.ci.model.dto.StringParmDTO;
import com.cgc.venus.server.ci.model.entity.*;
import com.cgc.venus.server.ci.model.vo.*;
import com.cgc.venus.server.ci.utils.ConvertUtil;
import com.cgc.venus.server.ci.utils.XmlUtil;
import com.cgc.venus.server.core.base.AbstractBaseService;
import com.cgc.venus.server.core.utils.StringUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.offbytwo.jenkins.JenkinsServer;
import com.offbytwo.jenkins.model.BuildWithDetails;
import com.offbytwo.jenkins.model.Job;
import com.offbytwo.jenkins.model.JobWithDetails;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by 业哥 on 2018/8/8.
 */
@Service
public class CIServiceImpl extends AbstractBaseService implements CIService {
    private static Logger logger = LogManager.getLogger("fileLogger");
    private final int JOB_TYPE_SHELL = 99;
    private final int JOB_TYPE_CODE = 1;
    private final int JOB_TYPE_MAVEN = 2;
    private final int JOB_TYPE_NODEJS = 3;
    private final int JOB_TYPE_DOCKER = 4;

    private final int DOCKER_VERSION_STRATEGY_TIMESTAMP = 1;
    private final int DOCKER_VERSION_STRATEGY_PARA = 2;

    @Autowired
    private PipelineDao pipelineDao;
    @Autowired
    private CodeSourceDao codeSourceDao;
    @Value(value = "${ci.jenkinsUrl}")
    private String jenkinsUrl;
    @Value(value = "${ci.jenkinsUser}")
    private String jenkinsUser;
    @Value(value = "${ci.jenkinsPwd}")
    private String jenkinsPwd;

    @Value(value = "${harbor.baseUrl}")
    private String harborHost;
    @Value(value = "${harbor.adminUser}")
    private String harborUser;
    @Value(value = "${harbor.adminPassword}")
    private String harborPwd;
    @Value(value = "${ci.jdk}")
    private String jdk;

    public String getJenkinsUrl() {
        return jenkinsUrl;
    }

    public void setJenkinsUrl(String jenkinsUrl) {
        //logger.info("===============set url:================="+jenkinsUrl);
        this.jenkinsUrl = jenkinsUrl;
    }

    public String getJenkinsUser() {
        return jenkinsUser;
    }

    public void setJenkinsUser(String jenkinsUser) {
        this.jenkinsUser = jenkinsUser;
    }

    public String getJenkinsPwd() {
        return jenkinsPwd;
    }

    public void setJenkinsPwd(String jenkinsPwd) {
        this.jenkinsPwd = jenkinsPwd;
    }

    public String getJdk() {
        return jdk;
    }

    public void setJdk(String jdk) {
        this.jdk = jdk;
    }

    public String getHarborHost() {
        return harborHost;
    }

    public void setHarborHost(String harborHost) {
        this.harborHost = harborHost;
    }

    public String getHarborUser() {
        return harborUser;
    }

    public void setHarborUser(String harborUser) {
        this.harborUser = harborUser;
    }

    public String getHarborPwd() {
        return harborPwd;
    }

    public void setHarborPwd(String harborPwd) {
        this.harborPwd = harborPwd;
    }

    private JenkinsServer jenkinsServer;

    private JenkinsServer getJenkinsServer() throws Exception {
        if (jenkinsServer != null) {
            boolean flag = jenkinsServer.isRunning();
            if (!flag) {
                throw new Exception("jenkins服务异常,请检查服务地址或者权限!");
            }
            return jenkinsServer;
        }
        URI serverUri = null;
        try {
            serverUri = new URI(jenkinsUrl);
            jenkinsServer = new JenkinsServer(serverUri, jenkinsUser, jenkinsPwd);
            boolean flag = jenkinsServer.isRunning();
            if (!flag) {
                throw new Exception("jenkins服务异常,请检查服务地址或者权限!");
            }
            return jenkinsServer;
        } catch (URISyntaxException e) {
            throw e;
        }
    }

    @Override
    public void createJob(String jobName, String configXml) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job != null) {
            throw new Exception("job:[" + jobName + "]已经存在,job创建失败!");
        }
        getJenkinsServer().createJob(jobName, configXml, true);
    }

    @Override
    public void updateJob(String jobName, String configXml) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job == null) {
            throw new Exception("job:[" + jobName + "]不存在,job修改失败!");
        }
        getJenkinsServer().updateJob(jobName, configXml, true);
    }

    @Override
    public void deleteJob(String jobName) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job == null) {
            throw new Exception("job:[" + jobName + "]不存在,job删除失败!");
        }
        getJenkinsServer().deleteJob(jobName, true);
    }

    @Override
    public int buildJob(String jobName) throws Exception {
        try {
            Job job = getJenkinsServer().getJobs().get(jobName);
            if (job == null) {
                throw new Exception("job:[" + jobName + "]不存在,job执行失败!");
            }
            JobWithDetails jobWithDetails = getJenkinsServer().getJob(jobName);
            BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
            int lastNum = buildWithDetails.getNumber();
            int currentNum = lastNum + 1;
            job.build(true);
            return currentNum;
        } catch (Exception ex) {
            if ("Nothing is submitted".equals(ex.getMessage())) {
                throw new Exception("请传入job对应的参数!");
            } else {
                throw ex;
            }
        }
    }

    @Override
    public int buildJob(String jobName, Map<String, String> params) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job == null) {
            throw new Exception("job:[" + jobName + "]不存在,job执行失败!");
        }
        JobWithDetails jobWithDetails = getJenkinsServer().getJob(jobName);
        BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
        int lastNum = buildWithDetails.getNumber();
        int currentNum = lastNum + 1;
        job.build(params, true);
        return currentNum;
    }

    @Override
    public BuildWithDetails getBuildJobDetailByLastTime(String jobName) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job == null) {
            throw new Exception("job:[" + jobName + "]不存在,job执行失败!");
        }
        JobWithDetails jobWithDetails = getJenkinsServer().getJob(jobName);
        BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
        return buildWithDetails;
    }

    @Override
    public BuildWithDetails getBuildJobDetailByNumber(String jobName, int number) throws Exception {
        Job job = getJenkinsServer().getJobs().get(jobName);
        if (job == null) {
            throw new Exception("job:[" + jobName + "]不存在,job执行失败!");
        }
        JobWithDetails jobWithDetails = getJenkinsServer().getJob(jobName);
        if (jobWithDetails.getBuildByNumber(number) == null) {
            throw new Exception("job[" + jobName + "]没有第[" + number + "]次的build记录!");
        }
        BuildWithDetails buildWithDetails = jobWithDetails.getBuildByNumber(number).details();
        return buildWithDetails;
    }

    @Override
    public PageInfo<PipelineVO> findPipelinesByKey(String key, String namespace, int pageNum, int rowNum) throws Exception {
        JenkinsServer js = getJenkinsServer();
        PageHelper.startPage(pageNum, rowNum, true, true);
        List<CiPipeline> list = pipelineDao.findPipelineByKey(key, namespace);
        List<PipelineVO> volList = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        for (CiPipeline cp : list) {
            PipelineVO pv = new PipelineVO();
            BeanUtils.copyProperties(cp, pv, "pipelineConfigXml", "namespace", "keepBuildDay", "keepBuildNumber", "pipelineType", "lastUpdateTime", "createUser", "updateUser");//entity转vo
            volList.add(pv);
            //获取build信息
            Job job = js.getJobs().get(pv.getPipelineNameEn());
            if (job == null) {
                continue;
            }
            //logger.info("===============url:================="+this.getJenkinsUrl());
            JobWithDetails jobWithDetails = js.getJob(pv.getPipelineNameEn());
            if (jobWithDetails == null) {
                continue;
            }
            BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
            if (buildWithDetails != null) {
                Date date = new Date(buildWithDetails.getTimestamp());
                pv.setLastBuildTime(sdf.format(date));
                if (buildWithDetails.getResult() == null) {
                    pv.setLastBuildResult("BUILDING");
                } else {
                    pv.setLastBuildResult(buildWithDetails.getResult().name());
                }
                pv.setLastBuildDuration(buildWithDetails.getDuration());
                pv.setLastBuildNum(buildWithDetails.getNumber());
            }
        }
        PageInfo<PipelineVO> pageInfo = new PageInfo(volList);
        return pageInfo;
    }

    @Override
    public PipelineVO findPipelineByIdWithNoDetail(String id) throws Exception {
        JenkinsServer js = getJenkinsServer();
        CiPipeline cp = pipelineDao.findPipelineById(id);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        PipelineVO pv = new PipelineVO();
        BeanUtils.copyProperties(cp, pv, "pipelineConfigXml", "namespace", "keepBuildDay", "keepBuildNumber", "pipelineType", "lastUpdateTime", "createUser", "updateUser");//entity转vo

        //获取build信息
        Job job = js.getJobs().get(pv.getPipelineNameEn());
        if (job == null) {
            return null;
        }
        JobWithDetails jobWithDetails = js.getJob(pv.getPipelineNameEn());
        if (jobWithDetails == null) {
            return null;
        }
        BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
        if (buildWithDetails != null) {
            Date date = new Date(buildWithDetails.getTimestamp());
            pv.setLastBuildTime(sdf.format(date));
            if (buildWithDetails.getResult() == null) {
                pv.setLastBuildResult("BUILDING");
            } else {
                pv.setLastBuildResult(buildWithDetails.getResult().name());
            }
            pv.setLastBuildDuration(buildWithDetails.getDuration());
            pv.setLastBuildNum(buildWithDetails.getNumber());
        }
        return pv;
    }

    /**
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    public PipelineVO findPipelineById(String id) throws Exception {
        JenkinsServer js = getJenkinsServer();
        CiPipeline ciPipeline = pipelineDao.findPipelineById(id);
        List<PipelinePara> pps = pipelineDao.findPipelineParaByPipelineId(id);
        List<PipelineStage> pss = pipelineDao.findPipelineStageByPipelineId(id);

        PipelineVO pv = new PipelineVO();
        BeanUtils.copyProperties(ciPipeline, pv, "pipelineConfigXml");
        pv.setLastBuildResult(null);
        pv.setLastBuildDuration(null);
        pv.setLastBuildNum(null);
        pv.setLastBuildTime(null);

        List<PipelineParaVO> ppvs = new ArrayList<>();
        pv.setPps(ppvs);
        for (PipelinePara pp : pps) {
            PipelineParaVO ppv = new PipelineParaVO();
            BeanUtils.copyProperties(pp, ppv);
            ppvs.add(ppv);
        }

        List<PipelineStageVO> psvs = new ArrayList<>();
        pv.setPss(psvs);
        for (PipelineStage ps : pss) {
            PipelineStageVO psv = new PipelineStageVO();
            BeanUtils.copyProperties(ps, psv);
            List<PipelineJob> pjs = pipelineDao.findPipelineJobByPipelineIdAndStageId(psv.getPipeline(), psv.getId());
            List<PipelineJobVO> pjvs = new ArrayList<>();
            for (PipelineJob pj : pjs) {
                PipelineJobVO pjv = new PipelineJobVO();
                BeanUtils.copyProperties(pj, pjv);
                pjvs.add(pjv);
            }
            psv.setPjs(pjvs);
            psvs.add(psv);
        }
        return pv;
    }

    @Override
    @Transactional
    public int addPipeline(PipelineVO pipelineVO) throws Exception {
        JenkinsServer js = getJenkinsServer();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss-SSS");
        String pipelineNameEn = "pl-" + sdf.format(new Date());//格式:pl-20181118145412456
        Job job = js.getJobs().get(pipelineNameEn);
        if (job != null) {
            throw new Exception("集成流水线:[" + pipelineNameEn + "]已经存在,job创建失败!");
        }
        ////////////////////////////////////////////////////////
        String pipeLineId = StringUtil.getUUID();
        CiPipeline cp = handleCiPipeline(pipelineVO, pipeLineId, pipelineNameEn);
        ///////////////////////////////////////////////////////
        try {
            pipelineDao.insertCiPipeline(cp);
        } catch (Exception e) {
            throw new Exception("流水线名称[" + cp.getPipelineName() + "]已经存在,请输入其他名称!");
        }

        //基于Jenkins创建集成流水线
        try {
            js.createJob(cp.getPipelineNameEn(), cp.getPipelineConfigXml(), true);
        } catch (Exception e) {
            //创建失败,删除创建的对象
            pipelineDao.deleteCiPipelineById(pipeLineId);
            pipelineDao.deletePipelineParaByPipelineId(pipeLineId);
            pipelineDao.deletePipelineStageByPipelineId(pipeLineId);
            pipelineDao.deletePipelineJobByPipelineId(pipeLineId);
            throw e;
        }
        return 1;
    }

    @Override
    @Transactional
    public int updatePipeline(PipelineVO pipelineVO) throws Exception {
        JenkinsServer js = getJenkinsServer();
        Job job = js.getJobs().get(pipelineVO.getPipelineNameEn());
        boolean isCreateJob=false;
        if (job == null) {
            isCreateJob=true;
            //throw new Exception("集成流水线:[" + pipelineVO.getPipelineNameEn() + "]不存在,集成流水线失败!");
        }
        //处理db
        String pipeLineId = pipelineVO.getId();
        String pipelineNameEn = pipelineVO.getPipelineNameEn();
        //先删除
        pipelineDao.deletePipelineParaByPipelineId(pipeLineId);
        pipelineDao.deletePipelineStageByPipelineId(pipeLineId);
        pipelineDao.deletePipelineJobByPipelineId(pipeLineId);
        //再更新明细表
        CiPipeline cp = handleCiPipeline(pipelineVO, pipeLineId, pipelineNameEn);
        //再更新流水线主表
        try {
            pipelineDao.updateCiPipeline(cp);
        } catch (Exception e) {
            throw new Exception("流水线名称[" + cp.getPipelineName() + "]已经存在,请输入其他名称!");
        }
        //处理Jenkins服务流水线对象的更新
        if(isCreateJob){
            js.createJob(cp.getPipelineNameEn(), cp.getPipelineConfigXml(), true);
        }else{
            js.updateJob(pipelineNameEn, cp.getPipelineConfigXml(), true);
        }
        return 1;
    }

    @Override
    @Transactional
    public int deletePipeline(String id, String pipelineNameEn) throws Exception {
        JenkinsServer js = getJenkinsServer();
        Job job = js.getJobs().get(pipelineNameEn);
        if (job == null) {
            throw new Exception("集成流水线:[" + pipelineNameEn + "]不存在,集成流水线删除失败!");
        }
        //Jenkins中删除流水线对象
        js.deleteJob(pipelineNameEn, true);
        //删除db对象
        pipelineDao.deleteCiPipelineById(id);
        pipelineDao.deletePipelineParaByPipelineId(id);
        pipelineDao.deletePipelineStageByPipelineId(id);
        pipelineDao.deletePipelineJobByPipelineId(id);
        return 1;
    }

    @Override
    @Transactional
    public int buildPipeline(String id, String pipelineNameEn, List<PipelineParaVO> ppvs) throws Exception {
        JenkinsServer js = getJenkinsServer();
        Job job = js.getJobs().get(pipelineNameEn);
        if (job == null) {
            CiPipeline cp = pipelineDao.findPipelineById(id);
            if (cp == null) {
                throw new Exception("集成流水线:[" + pipelineNameEn + "]不存在,构建失败!");
            }
            js.createJob(pipelineNameEn, cp.getPipelineConfigXml(), true);
            job = js.getJobs().get(pipelineNameEn);
        }
        JobWithDetails jobWithDetails = js.getJob(pipelineNameEn);
        BuildWithDetails buildWithDetails = jobWithDetails.getLastBuild().details();
        int lastNum = buildWithDetails.getNumber();
        int currentNum = lastNum + 1;
        //logger.info("===============url:================="+this.getJenkinsUrl());
        if (ppvs == null || ppvs.size() == 0) {
            String jobUrl=job.getUrl();
            //logger.info("===============jobUrl:================="+jobUrl);
            job.build(true);
        } else {
            //更新参数表start
            pipelineDao.deletePipelineParaByPipelineId(id);
            //批量插入流水线参数表
            List<PipelinePara> pps = new ArrayList<>();
            int i = 1;
            for (PipelineParaVO ppv : ppvs) {
                PipelinePara pp = new PipelinePara();
                BeanUtils.copyProperties(ppv, pp);//复制属性
                pp.setId(StringUtil.getUUID());//设置属性 start
                pp.setPipeline(id);
                if (pp.getParaValue() == null || pp.getParaValue().equals("")) {
                    pp.setParaValue(pp.getParaDefaultValue());//默认初始值等于默认值
                }
                pp.setOrderNumber(i++);
                pp.setCreateUser(ppv.getCreateUser());
                pp.setUpdateUser(ppv.getUpdateUser());//设置属性 end
                pps.add(pp);
            }
            if (pps != null && pps.size() > 0) {
                pipelineDao.batchInsertCiPipelinePara(pps);
            }
            //更新参数表end
            Map<String, String> params = new HashMap<>();
            for (PipelineParaVO ppv : ppvs) {
                params.put(ppv.getParaName(), ppv.getParaValue());
            }
            job.build(params, true);
        }
        return currentNum;
    }

    @Override
    public PipelineBuildLogVO findPipelineBuildLog(String id, String pipelineNameEn, int buildNum) throws Exception {
        JenkinsServer js = getJenkinsServer();
        Job job = js.getJobs().get(pipelineNameEn);
        if (job == null) {
            throw new Exception("集成流水线[" + pipelineNameEn + "]不存在,流水线执行失败!");
        }
        JobWithDetails jobWithDetails = js.getJob(pipelineNameEn);
        if (jobWithDetails.getBuildByNumber(buildNum) == null) {
            //throw new Exception("集成流水线[" + pipelineNameEn + "]没有第[" + buildNum + "]次的build记录!");
            //throw new Exception("no log record");
            return null;
        }
        BuildWithDetails buildWithDetails = jobWithDetails.getBuildByNumber(buildNum).details();
        PipelineBuildLogVO pipelineBuildLogVO = ConvertUtil.buildWithDetailToBuildDetail(buildWithDetails, pipelineNameEn);
        return pipelineBuildLogVO;
    }

    @Override
    public List<PipelineBuildLogVO> findPipelineBuildLogs(String id, String pipelineNameEn, int buildNum) throws Exception {
        JenkinsServer js = getJenkinsServer();
        Job job = js.getJobs().get(pipelineNameEn);
        if (job == null) {
            throw new Exception("集成流水线[" + pipelineNameEn + "]不存在,流水线执行失败!");
        }
        JobWithDetails jobWithDetails = js.getJob(pipelineNameEn);
        List<PipelineBuildLogVO> pipelineBuildLogVOs = new ArrayList<>();
        for (int i = buildNum; i >= 1; i--) {
            if (jobWithDetails.getBuildByNumber(i) == null) {
                continue;
                //throw new Exception("集成流水线[" + pipelineNameEn + "]没有第[" + i + "]次的build记录!");
            }
            BuildWithDetails buildWithDetails = jobWithDetails.getBuildByNumber(i).details();
            pipelineBuildLogVOs.add(ConvertUtil.buildWithDetailToBuildDetail(buildWithDetails, pipelineNameEn));
        }
        return pipelineBuildLogVOs;
    }


    private CiPipeline handleCiPipeline(PipelineVO pipelineVO, String pipeLineId, String pipelineNameEn) throws Exception {
        PipelineJobDTO pipelineJobDTO = new PipelineJobDTO();//Jenkins流水线对象构建 对象
        pipelineJobDTO.setDesc("");//Jenkins流水线对象构建 属性
        pipelineJobDTO.setKeepBuildDay(pipelineVO.getKeepBuildDay());//Jenkins流水线对象构建 属性
        pipelineJobDTO.setKeepBuildNumber(pipelineVO.getKeepBuildNumber());//Jenkins流水线对象构建 属性

        //插入流水线主表(数据构造)
        CiPipeline cp = new CiPipeline();
        BeanUtils.copyProperties(pipelineVO, cp);//复制属性
        //String pipeLineId= StringUtil.getUUID();//设置属性 startcheng
        cp.setId(pipeLineId);
        cp.setPipelineNameEn(pipelineNameEn);
        cp.setPipelineType(1);//设置属性 end
        cp.setRemark("");

        //批量插入流水线参数表
        List<PipelineParaVO> ppvs = pipelineVO.getPps();
        List<PipelinePara> pps = new ArrayList<>();

        List<StringParmDTO> spds = new ArrayList<>();//Jenkins流水线参数集合对象构建
        int i = 1;
        for (PipelineParaVO ppv : ppvs) {
            PipelinePara pp = new PipelinePara();
            BeanUtils.copyProperties(ppv, pp);//复制属性
            pp.setId(StringUtil.getUUID());//设置属性 start
            if (pp.getParaValue() == null || pp.getParaValue().equals("")) {
                pp.setParaValue(pp.getParaDefaultValue());//默认初始值等于默认值
            }
            pp.setPipeline(pipeLineId);
            pp.setOrderNumber(i++);
            pp.setCreateUser(cp.getCreateUser());
            pp.setUpdateUser(cp.getUpdateUser());//设置属性 end
            pps.add(pp);

            spds.add(new StringParmDTO(pp.getParaName(), "", pp.getParaDefaultValue()));//Jenkins流水线参数集合对象构建
        }
        pipelineJobDTO.setStringParms(spds);//Jenkins流水线参数集合对象构建
        if (pps != null && pps.size() > 0) {
            try {
                pipelineDao.batchInsertCiPipelinePara(pps);
            } catch (Exception e) {
                throw new Exception("不能有重复的流水线参数名!");
            }
        }


        //批量插入流水线阶段表
        List<PipelineStageVO> psvs = pipelineVO.getPss();
        List<PipelineStage> pss = new ArrayList<>();
        int j = 1;
        int j1 = 1;
        List<PipelineStageDTO> psds = new ArrayList<>();//Jenkins流水线阶段集合对象构建
        for (PipelineStageVO psv : psvs) {
            PipelineStage ps = new PipelineStage();
            BeanUtils.copyProperties(psv, ps);//复制属性
            String stageId = StringUtil.getUUID();
            ps.setId(stageId);//设置属性 start
            ps.setNamespace(pipelineVO.getNamespace());//
            ps.setPipeline(pipeLineId);
            ps.setStageNameEn(ps.getStageName());//
            ps.setParentStage("");
            ps.setOrderNumber(j1++);
            ps.setCreateUser(cp.getCreateUser());
            ps.setUpdateUser(cp.getUpdateUser());
            ps.setRemark("");//设置属性 end

            //批量插入流水线任务
            List<PipelineJobVO> pjvs = psv.getPjs();
            List<PipelineJob> pjs = new ArrayList<>();
            int k = 1;
            List<String> shellCmd = new ArrayList<>();//Jenkins流水线阶段shell脚本集合对象构建
            for (PipelineJobVO pjv : pjvs) {
                PipelineJob pj = new PipelineJob();
                List<String> ignoreProperty = Arrays.asList("id", "namespace", "pipeline", "stage", "parentJob",
                        "orderNumber", "createUser", "updateUser", "remark", "createTime", "lastUpdateTime");
                if (pj.getJobType() == JOB_TYPE_SHELL) {
                    ignoreProperty.addAll(Arrays.asList("codeSource", "jdkVersion", "jdkPath", "mavenShell",
                            "nodejsShell", "dockerImageName", "dockerVersionStrategy",
                            "dockerImageVersionPara"));
                } else if (pj.getJobType() == JOB_TYPE_CODE) {
                    ignoreProperty.addAll(Arrays.asList("jdkVersion", "jdkPath", "mavenShell",
                            "nodejsShell", "dockerImageName", "dockerVersionStrategy",
                            "dockerImageVersionPara"));
                } else if (pj.getJobType() == JOB_TYPE_MAVEN) {
                    ignoreProperty.addAll(Arrays.asList("codeSource",
                            "nodejsShell", "dockerImageName", "dockerVersionStrategy",
                            "dockerImageVersionPara"));
                } else if (pj.getJobType() == JOB_TYPE_NODEJS) {
                    ignoreProperty.addAll(Arrays.asList("codeSource", "jdkVersion", "jdkPath", "mavenShell",
                            "dockerImageName", "dockerVersionStrategy", "dockerImageVersionPara"));
                } else if (pj.getJobType() == JOB_TYPE_DOCKER) {
                    ignoreProperty.addAll(Arrays.asList("codeSource", "jdkVersion", "jdkPath", "mavenShell",
                            "nodejsShell"));
                }
                BeanUtils.copyProperties(pjv, pj, (String[]) ignoreProperty.toArray());

                pj.setId(StringUtil.getUUID());//设置属性 start
                pj.setNamespace(pipelineVO.getNamespace());
                pj.setPipeline(pipeLineId);
                pj.setStage(stageId);
                pj.setParentJob("");
                pj.setOrderNumber(k++);
                pj.setCreateUser(cp.getCreateUser());
                pj.setUpdateUser(cp.getUpdateUser());
                pj.setRemark("");
                pjs.add(pj);


                //处理构建目录  start
                StringBuffer sbShell = new StringBuffer("");
                if (pj.getBuildDir() != null && !pj.getBuildDir().equals("")) {
                    String location = pj.getBuildDir();
                    if (location.startsWith("/")) {
                        location = location.replaceFirst("/", "");
                    }
                    sbShell.append("if [ ! -d \"$WORKSPACE/" + location + "\" ]; then \r\n");
                    sbShell.append(" mkdir -p $WORKSPACE/" + location + " \r\n");
                    sbShell.append("fi \r\n");
                    sbShell.append("cd $WORKSPACE/" + location + "\r\n");
                }
                //处理构建目录  end

                if (pj.getJobType() == JOB_TYPE_SHELL) {
                    //job类型为执行shell脚本
                    sbShell.append(pj.getShell());
                    String shellSript = sbShell.toString();
                    shellCmd.add(shellSript);
                    //pj.setShell(shellSript);
                    pj.setDockerImageName(null);
                } else if (pj.getJobType() == JOB_TYPE_CODE) {
                    //job类型为获取代码
                    //构建shell脚本 start
                    CodeSource codeSource = codeSourceDao.findCodeSourceById(pj.getCodeSource());
                    sbShell.append("svn co --username "
                            + codeSource.getCodeUserName()
                            + " --password "
                            + codeSource.getCodePwd()
                            + " "
                            + codeSource.getCodeUrl()
                            +" --force --no-auth-cache");
                    //构建shell脚本 end
                    String shellSript = sbShell.toString();
                    shellCmd.add(shellSript);
                    pj.setShell(shellSript);
                    pj.setDockerImageName(null);
                } else if (pj.getJobType() == JOB_TYPE_MAVEN) {
                    //job类型为maven构建
                    //构建shell脚本 start
                    sbShell.append("export JAVA_HOME=" + pj.getJdkPath() + " \r\n");
                    sbShell.append(pj.getMavenShell());
                    //构建shell脚本 end
                    String shellSript = sbShell.toString();
                    shellCmd.add(shellSript);
                    pj.setShell(shellSript);
                    pj.setDockerImageName(null);
                } else if (pj.getJobType() == JOB_TYPE_NODEJS) {
                    //job类型为nodejs构建
                    //构建shell脚本 start
                    sbShell.append(pj.getNodejsShell());
                    //构建shell脚本 end
                    String shellSript = sbShell.toString();
                    shellCmd.add(shellSript);
                    pj.setShell(shellSript);
                    pj.setDockerImageName(null);
                } else if (pj.getJobType() == JOB_TYPE_DOCKER) {
                    //job类型为docker镜像构建
                    //构建shell脚本 start
                    String harborProject = pipelineDao.findHarborProjectNameByNamespaceId(pj.getNamespace());
                    String imageVersion = "";
                    //先删除旧镜像
                    //代码待续...
                    if (pj.getDockerVersionStrategy() == DOCKER_VERSION_STRATEGY_PARA) {
                        //版本策略为参数传递
                        String paraName = pj.getDockerImageVersionPara();
                        imageVersion = "v$" + paraName;
                        sbShell.append("docker build -t " + harborHost + "/" + harborProject + "/" + pj.getDockerImageName() + ":" + imageVersion + " . \r\n");
                    } else {
                        //时间戳
                        sbShell.append("IMV=`date \"+%Y%m%d-%H%M%S\"` \r\n");
                        sbShell.append("docker build -t " + harborHost + "/" + harborProject + "/" + pj.getDockerImageName() + ":v$IMV . \r\n");
                        imageVersion = "v$IMV";
                    }
                    sbShell.append("docker login -u " + harborUser + " -p " + harborPwd + " " + harborHost + " \r\n");
                    sbShell.append("docker push " + harborHost + "/" + harborProject + "/" + pj.getDockerImageName() + ":" + imageVersion + " \r\n");//推镜像到仓库
                    sbShell.append("docker rmi " + harborHost + "/" + harborProject + "/" + pj.getDockerImageName() + ":" + imageVersion);//删除镜像
                    //构建shell脚本 end
                    String shellSript = sbShell.toString();
                    shellCmd.add(shellSript);
                    pj.setShell(shellSript);
                }
            }
            if (pjs != null && pjs.size() > 0) {
                try {
                    pipelineDao.batchInsertCiPipelineJob(pjs);
                } catch (Exception e) {
                    throw new Exception("同一个阶段内不能有重复的任务名称!");
                }
            }
            pss.add(ps);
            psds.add(new PipelineStageDTO(ps.getStageNameEn(), shellCmd));//Jenkins流水线阶段集合对象构建
        }
        pipelineJobDTO.setPipelineStages(psds);//Jenkins流水线阶段集合对象构建
        if (pss != null && pss.size() > 0) {
            try {
                pipelineDao.batchInsertCiPipelineStage(pss);
            } catch (Exception e) {
                throw new Exception("不能有重复的阶段名称!");
            }
        }
        String pipelineConfigXml = XmlUtil.pipelineJobToXml(pipelineJobDTO);
        //插入流水线主表(入db)
        cp.setPipelineConfigXml(pipelineConfigXml);
        return cp;
    }

    @Override
    public List<JdkVO> getJdkConfig() throws Exception {
        List<JdkVO> jdkVOs = new ArrayList<>();
        if (jdk == null || jdk.equals("")) {
            return jdkVOs;
        }
        String[] tmp = jdk.split(",");
        for (String s : tmp) {
            JdkVO jv = new JdkVO();
            String[] tmp1 = s.split(":");
            jv.setJdkVersion(tmp1[0]);
            jv.setJdkPath(tmp1[1]);
            jdkVOs.add(jv);
        }
        return jdkVOs;
    }

    @Override
    public List<PipelineParaVO> findPipelineParaByPipelineId(String pipelineId) throws Exception {
        List<PipelinePara> pps = pipelineDao.findPipelineParaByPipelineId(pipelineId);
        List<PipelineParaVO> ppvs = new ArrayList<>();
        for (PipelinePara pp : pps) {
            PipelineParaVO ppv = new PipelineParaVO();
            BeanUtils.copyProperties(pp, ppv, "pipeline", "orderNumber", "createTime", "lastUpdateTime", "createUser", "updateUser", "remark");//复制属性
            ppvs.add(ppv);
        }
        return ppvs;
    }


}